using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Forest.Cat.Domain.Entities;
using Forest.Core;
using Forest.Core.Caching;
using Forest.Core.Data;
using Forest.Core.Events;
using Forest.Cat.Domain.Shared;

namespace Forest.Cat.Domain.Services.Catalog
{
    public partial class NewsService : INewsService
    {
        #region Constants
        private const string NEWS_BY_ID_KEY = "news.id-{0}";
        private const string NEWS_PATTERN_KEY = "news.";
        #endregion

        #region Fields
        private readonly IRepository<News> _newsRepository;
        private readonly ICacheManager _cacheManager;
        private readonly IEventPublisher _eventPublisher;
        #endregion

        #region Ctor
        public NewsService(IRepository<News> newsRepository, ICacheManager cacheManager, IEventPublisher eventPublisher)
        {
            _newsRepository = newsRepository;
            _cacheManager = cacheManager;
            _eventPublisher = eventPublisher;
        }
        #endregion

        #region Base Methods
        public virtual void DeleteNews(News news)
        {
            if (news == null)
                throw new ArgumentNullException("News");

            _newsRepository.Delete(news);
            _cacheManager.RemoveByPattern(NEWS_PATTERN_KEY);
            _eventPublisher.EntityDeleted(news);
        }

        public News GetNewsById(Guid newsId)
        {
            if (newsId == Guid.Empty)
                return null;
            string key = string.Format(NEWS_BY_ID_KEY, newsId);

            return _cacheManager.Get(key, () =>
            {
                var cl = _newsRepository.GetById(newsId);
                return cl;
            });
        }

        public virtual IPagedList<News> GetAllNewss(int pageIndex, int pageSize)
        {
            var query = _newsRepository.Table;
            query = query.OrderBy(w => w.Id);
            var items = new PagedList<News>(query, pageIndex, pageSize);
            return items;
        }

        public virtual void InsertNews(News news)
        {
            if (news == null)
                throw new ArgumentNullException("News");
            _newsRepository.Insert(news);
            _cacheManager.RemoveByPattern(NEWS_PATTERN_KEY);
            _eventPublisher.EntityInserted(news);
        }

        public virtual void UpdateNews(News news)
        {
            if (news == null)
                throw new ArgumentNullException("News");
            _newsRepository.Update(news);
            _cacheManager.RemoveByPattern(NEWS_PATTERN_KEY);
            _eventPublisher.EntityUpdated(news);
        }
        #endregion

        #region Extend Methods
        public IQueryable<News> GetNewByTab(NewsTab newsTab,int top=11)
        {
            var newTabValue = (int)newsTab;
            return _newsRepository.Table.Where(x => x.Tab.Value.Equals(newTabValue) && x.Published).OrderByDescending(n => n.PostedOn).Take(top);
        }

        #endregion
    }
}
